package com.yangxu.hospital.tools.utils;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static net.dreamlu.mica.core.utils.$.formatTime;

public class TimeUtils {

    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("MM-dd");
    private static final DateTimeFormatter DAY_OF_WEEK_FORMATTER = DateTimeFormatter.ofPattern("EEEE", java.util.Locale.CHINA);
    private static final DateTimeFormatter FULL_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    /**
     * 获取从今天开始往后指定周数的特定日期的时间段，按指定分钟间隔生成排班号
     *
     * @param weeks 周数
     * @param dayOfWeek 特定日期（如 DayOfWeek.MONDAY）
     * @param interval 分钟间隔
     * @param startHour 上午开始小时
     * @param endHour 上午结束小时
     * @param startMinute 上午开始分钟
     * @param endMinute 上午结束分钟
     * @return 包含排班号的列表
     */
    public static List<String> getSpecificDaySchedule(int weeks, DayOfWeek dayOfWeek, int interval, int startHour, int endHour, int startMinute, int endMinute) {
        LocalDate today = LocalDate.now();
        LocalDate startDate = today.with(TemporalAdjusters.nextOrSame(dayOfWeek));
        LocalDate endDate = startDate.plusWeeks(weeks).minusDays(1);

        List<String> schedule = new ArrayList<>();

        for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusWeeks(1)) {
            LocalDateTime startTime = LocalDateTime.of(date, LocalTime.of(startHour, startMinute));
            LocalDateTime endTime = LocalDateTime.of(date, LocalTime.of(endHour, endMinute));

            int slotNumber = 1;
            while (!startTime.isAfter(endTime)) {
                schedule.add(formatDateTime(startTime) + " - " + slotNumber);
                startTime = startTime.plusMinutes(interval);
                slotNumber++;
            }
        }

        return schedule;
    }

    /**
     * 获取从今天开始往后指定天数的时间段，按指定分钟间隔生成排班号
     *
     * @param days 天数
     * @param interval 分钟间隔
     * @param startHour 上午开始小时
     * @param endHour 上午结束小时
     * @param startMinute 上午开始分钟
     * @param endMinute 上午结束分钟
     * @return 包含排班号的列表
     */
    public static List<String> getFutureSchedule(int days, int interval, int startHour, int endHour, int startMinute, int endMinute) {
        LocalDate today = LocalDate.now();
        LocalDate endDate = today.plusDays(days);

        List<String> schedule = new ArrayList<>();

        for (LocalDate date = today; !date.isAfter(endDate); date = date.plusDays(1)) {
            LocalDateTime startTime = LocalDateTime.of(date, LocalTime.of(startHour, startMinute));
            LocalDateTime endTime = LocalDateTime.of(date, LocalTime.of(endHour, endMinute));

            int slotNumber = 1;
            while (!startTime.isAfter(endTime)) {
                schedule.add(formatDateTime(startTime) + " - " + slotNumber);
                startTime = startTime.plusMinutes(interval);
                slotNumber++;
            }
        }

        return schedule;
    }

    /**
     * 获取指定日期的时间段，按指定分钟间隔生成排班号
     *
     * @param date 指定日期
     * @param startTime 开始时间 (HH:mm)
     * @param endTime 结束时间 (HH:mm)
     * @param interval 分钟间隔
     * @return 包含排班号的列表
     */
    public static List<String> getDailySchedule(LocalDate date, String startTime, String endTime, int interval) {
        List<String> schedule = new ArrayList<>();

        LocalTime startLocalTime = LocalTime.parse(startTime);
        LocalTime endLocalTime = LocalTime.parse(endTime);

        LocalDateTime startDateTime = LocalDateTime.of(date, startLocalTime);
        LocalDateTime endDateTime = LocalDateTime.of(date, endLocalTime);

        int slotNumber = 1;
        while (!startDateTime.isAfter(endDateTime)) {
            schedule.add(formatDateTime(startDateTime) + " - " + slotNumber);
            startDateTime = startDateTime.plusMinutes(interval);
            slotNumber++;
        }

        return schedule;
    }
    /**
     * 获取指定日期的时间段，按指定分钟间隔生成排班号，并返回 Map 形式
     *
     * @param date 指定日期
     * @param startTime 开始时间 (LocalTime)
     * @param endTime 结束时间 (LocalTime)
     * @param interval 分钟间隔
     * @return 包含排班号和对应时间的 Map
     */
    public static Map<Integer, String> getDailySchedule(LocalDate date, LocalTime startTime, LocalTime endTime, int interval) {
        Map<Integer, String> schedule = new HashMap<>();

        LocalDateTime startDateTime = LocalDateTime.of(date, startTime);
        LocalDateTime endDateTime = LocalDateTime.of(date, endTime);

        int slotNumber = 1;
        while (!startDateTime.isAfter(endDateTime)) {
            schedule.put(slotNumber, formatTime(startDateTime.toLocalTime()));
            startDateTime = startDateTime.plusMinutes(interval);
            slotNumber++;
        }

        return schedule;
    }
    /**
     * 获取从当前日期开始往后14天的日期和对应的星期几，并标注是否是今天
     *
     * @return 包含日期、星期几及是否是今天的列表
     */
    public static List<Map<String, Object>> getNext14DaysWithDayOfWeek() {
        LocalDate today = LocalDate.now();
        LocalDate endDate = today.plusDays(14);

        List<Map<String, Object>> dates = new ArrayList<>();

        for (LocalDate date = today; !date.isAfter(endDate); date = date.plusDays(1)) {
            String formattedDate = DATE_FORMATTER.format(date);
            String dayOfWeek = date.format(DAY_OF_WEEK_FORMATTER);
            boolean isToday = date.equals(today);
            String fullDate = FULL_DATE_FORMATTER.format(date);

            Map<String, Object> dateInfo = new HashMap<>();
            dateInfo.put("date", formattedDate);
            dateInfo.put("week", dayOfWeek);
            dateInfo.put("isToday", isToday);
            dateInfo.put("fullDate", fullDate);

            dates.add(dateInfo);
        }

        return dates;
    }

    /**
     * 根据给定的完整日期，获取当天对应的星期几
     *
     * @param fullDate 完整日期字符串 (格式: yyyy-MM-dd)
     * @return 当天对应的星期几（中文）
     */
    public static String getDayOfWeekByFullDate(String fullDate) {
        LocalDate date = LocalDate.parse(fullDate, FULL_DATE_FORMATTER);
        return date.format(DAY_OF_WEEK_FORMATTER);
    }

    /**
     * 格式化日期时间
     *
     * @param dateTime 日期时间
     * @return 格式化的字符串
     */
    private static String formatDateTime(LocalDateTime dateTime) {
        return DATE_TIME_FORMATTER.format(dateTime);
    }

    /**
     * 获取当前月份内所有指定星期几的日期
     *
     * @param dayOfWeekStr 星期几的字符串（如 "Monday", "Tuesday", ..., "Sunday"）
     * @return 包含日期的列表，格式为 yyyy-MM-dd
     */
    public static List<String> getWeekdaysInCurrentMonth(String dayOfWeekStr) {
        LocalDate today = LocalDate.now();
        YearMonth currentYearMonth = YearMonth.from(today);
        LocalDate firstDayOfMonth = currentYearMonth.atDay(1);
        LocalDate lastDayOfMonth = currentYearMonth.atEndOfMonth();

        DayOfWeek targetDayOfWeek = DayOfWeek.valueOf(dayOfWeekStr.toUpperCase());

        List<String> weekdays = new ArrayList<>();

        // 找到第一个目标星期几的日期
        LocalDate currentDate = firstDayOfMonth.with(TemporalAdjusters.nextOrSame(targetDayOfWeek));

        while (!currentDate.isAfter(lastDayOfMonth)) {
            weekdays.add(FULL_DATE_FORMATTER.format(currentDate));
            currentDate = currentDate.plusWeeks(1);
        }

        return weekdays;
    }

    /**
     * 获取从现在开始30天内的所有指定星期几的日期
     *
     * @param dayOfWeekStr 星期几的字符串（如 "Monday", "Tuesday", ..., "Sunday"）
     * @return 包含日期的列表，格式为 yyyy-MM-dd
     */
    public static List<String> getWeekdaysInNext30Days(String dayOfWeekStr) {
        LocalDate today = LocalDate.now();
        LocalDate endDate = today.plusDays(29); // 因为循环会加一周，所以这里减一天

        DayOfWeek targetDayOfWeek = DayOfWeek.valueOf(dayOfWeekStr.toUpperCase());

        List<String> weekdays = new ArrayList<>();

        // 找到第一个目标星期几的日期
        LocalDate currentDate = today.with(TemporalAdjusters.nextOrSame(targetDayOfWeek));

        while (!currentDate.isAfter(endDate)) {
            weekdays.add(FULL_DATE_FORMATTER.format(currentDate));
            currentDate = currentDate.plusWeeks(1);
        }

        return weekdays;
    }

    public static void main(String[] args) {



        // 测试 getDailySchedule
        System.out.println("Daily Schedule for 2024-12-10 from 07:00 to 11:30 with 15-minute intervals:");
        LocalDate specificDate = LocalDate.of(2024, 12, 10);
        LocalTime startTime = LocalTime.of(7, 0);
        LocalTime endTime = LocalTime.of(11, 30);
        System.out.println(getDailySchedule(specificDate, startTime, endTime, 15));
//        // 示例：获取未来两周的周一排班号
//        List<String> specificDaySchedule = getSpecificDaySchedule(4, DayOfWeek.MONDAY, 7, 7, 11, 0, 30);
//        for (String slot : specificDaySchedule) {
//            System.out.println(slot);
//        }
        // 测试 getWeekdaysInNext30Days
//        System.out.println("\nWeekdays in Next 30 Days:");
//        System.out.println(getWeekdaysInNext30Days("Wednesday"));
//
//        // 示例：获取从今天开始往后14天的排班号
//        List<String> futureSchedule = getFutureSchedule(14, 7, 7, 11, 0, 30);
//        for (String slot : futureSchedule) {
//            System.out.println(slot);
//        }
//
//        // 示例：获取从今天开始往后14天的日期和对应的星期几以及是否是今天
//        List<Map<String, Object>> next14DaysWithDayOfWeek = getNext14DaysWithDayOfWeek();
//        for (Map<String, Object> dateInfo : next14DaysWithDayOfWeek) {
//            System.out.println("date=" + dateInfo.get("date")
//                    + ", week=" + dateInfo.get("week")
//                    + ", isToday=" + dateInfo.get("isToday"));
//        }

        // 示例：获取当前月份内所有的周一日期
//        List<String> mondays = getWeekdaysInCurrentMonth("Monday");
//        System.out.println("Mondays in current month: " + mondays);
//
//        // 示例：获取当前月份内所有的周二日期
//        List<String> tuesdays = getWeekdaysInCurrentMonth("Tuesday");
//        System.out.println("Tuesdays in current month: " + tuesdays);
    }
}